using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace CoolCode.Web.Mvc.UI.Grid
{
	/// <summary>
	/// Renders a grid as an HTML table.
	/// </summary>
	public class HtmlTableGridRenderer<T> : GridRenderer<T> where T : class
	{
		private const string DefaultCssClass = "grid";

		public HtmlTableGridRenderer() { }

		public HtmlTableGridRenderer(ViewEngineCollection engines)
			: base(engines)
		{

		}

		protected override void RenderGridStart()
		{
			//RenderText(string.Format("<div id=\"{0}\" class=\"{1}\" style=\"{2}\">", GridModel.Container, "bbit-grid", ""));// "height:500px;"
			TagBuilder tagBuilder = Dom.CreateTag("div");
			tagBuilder.AddCssClass("bbit-grid");
			tagBuilder.GenerateId(GridModel.Container);
		}

		protected override void RenderGridEnd()
		{
			//RenderText("</div>");
			string html = Dom.ToString();
			Writer.Write(html);
		}

		protected override void RenderEmpty()
		{
			//string columns = string.Format("<td colspan=\"{0}\"><div style=\"height:20px\" /></td>", VisibleColumns().Count());
			//int i = 0;
			//while (i++ < rows)
			//{
			//    RenderText("<tr class=\"empty-row\">" + columns + "</tr>");
			//}

			//RenderHeadStart();
			//RenderText("<th/>");
			//RenderHeadEnd();
			//RenderBodyStart();
			//RenderText("<tr class=\"empty-text\"><td>" + GridModel.EmptyText + "</td></tr>");
			//RenderBodyEnd();

			RenderTableStart();
			RenderHeader();
			RenderBodyStart();

			TagBuilder tr = Dom.CreateTag("tr");
			tr.AddCssClass("erow empty-text");

			TagBuilder td = Dom.CreateTag("td");
			td.Attributes["colspan"] = "50";

			TagBuilder div = Dom.CreateTag("div");
			div.InnerHtml = GridModel.EmptyText;

			Dom.EndTag();
			Dom.EndTag();
			Dom.EndTag();

			RenderBodyEnd();
			RenderTableEnd();
		}


		protected override void RenderTableStart()
		{
			//string attributeString = BuildHtmlAttributes(GridModel.Attributes);
			//attributeString = AddSpaceIfNotEmpty(attributeString);

			//RenderText("<div class=\"bDiv\">");
			//RenderText(string.Format("<table{0} border=\"0\" cellpadding=\"0\" cellspacing=\"0\">", attributeString));

			TagBuilder div = Dom.CreateTag("div");
			div.AddCssClass("bDiv");

			TagBuilder tagBuilder = Dom.CreateTag("table"); 
			tagBuilder.Attributes["border"] = "0";
			tagBuilder.Attributes["cellpadding"] = "0";
			tagBuilder.Attributes["cellspacing"] = "0";
			CopyAttributes(GridModel.Attributes, tagBuilder.Attributes);

		}

		protected override void RenderTableEnd()
		{
			//RenderText("</table>");
			//RenderText("</div>");
			Dom.EndTag();
			Dom.EndTag();
		}

		protected override void RenderHeaderCellStart(GridColumn<T> column)
		{
			if (column.IsSortable)
			{
				string sortOrderCss = column.SortOptions.SortOrder == System.Data.SqlClient.SortOrder.Ascending ? "asc" : "desc";
				column.HeaderAttributes.AddIfNotExists("class", sortOrderCss);
			}

			//string attributeString = BuildHtmlAttributes(column.HeaderAttributes);

			//attributeString = AddSpaceIfNotEmpty(attributeString);

			//RenderText("<th>");
			//RenderText(string.Format("<div{0}>", attributeString));

			TagBuilder th = Dom.CreateTag("th");
			TagBuilder div = Dom.CreateTag("div");
			CopyAttributes(column.HeaderAttributes, div.Attributes);
		}

		protected override void RenderHeaderCellEnd()
		{
			//RenderText("</div>");
			//RenderText("</th>");
			Dom.EndTag();
			Dom.EndTag();
		}

		protected override void RenderRowStart(GridRowViewData<T> rowData)
		{
			var attributes = GridModel.Sections.Row.Attributes(rowData);
			attributes.AddIfNotExists("class", () => { return rowData.IsAlternate ? "erow" : "row"; });

			//string attributeString = BuildHtmlAttributes(attributes);
			//attributeString = AddSpaceIfNotEmpty(attributeString);

			//RenderText(string.Format("<tr{0}>", attributeString));

			TagBuilder tagBuilder = Dom.CreateTag("tr"); 
			CopyAttributes(attributes, tagBuilder.Attributes);
		}

		protected override void RenderRowEnd()
		{
			//RenderText("</tr>");
			Dom.EndTag();
		}

		protected override void RenderStartCell(GridColumn<T> column, GridRowViewData<T> rowData)
		{
			var attributes = column.Attributes(rowData);

			if (column.Width > 0)
			{
				AddStyleIfNotExists(attributes, "width", column.Width + "px");
			}

			//string attributeString = BuildHtmlAttributes(attributes);
			//attributeString = AddSpaceIfNotEmpty(attributeString);

			//RenderText("<td>");
			//RenderText(string.Format("<div{0}>", attributeString));


			TagBuilder td = Dom.CreateTag("td");
			TagBuilder div = Dom.CreateTag("div");
			CopyAttributes(attributes, div.Attributes);

		}

		protected override void RenderEndCell()
		{
			//RenderText("</div>");
			//RenderText("</td>");
			Dom.EndTag();
			Dom.EndTag();
		}

		protected override void RenderHeadStart()
		{
			var attributes = GridModel.Sections.HeaderRow.Attributes(new GridRowViewData<T>(null, false));
			//string attributeString = BuildHtmlAttributes(attributes);
			//attributeString = AddSpaceIfNotEmpty(attributeString);
 
			//RenderText(string.Format("<thead><tr{0}>", attributeString));

			TagBuilder thead = Dom.CreateTag("thead");
			TagBuilder tr = Dom.CreateTag("tr");
			CopyAttributes(attributes, tr.Attributes);
		}

		protected override void RenderHeadEnd()
		{
			//RenderText("</tr></thead>"); 
			Dom.EndTag();
			Dom.EndTag();
		}

		protected override void RenderBodyStart()
		{ 
			//RenderText("<tbody>");
			Dom.CreateTag("tbody");
		}

		protected override void RenderBodyEnd()
		{
			//RenderText("</tbody>"); 
			Dom.EndTag();
		}

		/// <summary>
		/// Converts the specified attributes dictionary of key-value pairs into a string of HTML attributes. 
		/// </summary>
		/// <returns></returns>
		private static string BuildHtmlAttributes(IDictionary<string, object> attributes)
		{
			if (attributes == null || attributes.Count == 0)
			{
				return string.Empty;
			}

			const string attributeFormat = "{0}=\"{1}\"";

			return string.Join(" ",
				   attributes.Select(pair => string.Format(attributeFormat, pair.Key, pair.Value)).ToArray()
			);
		}

		private static string AddSpaceIfNotEmpty(string value)
		{
			if (value.Length > 0)
			{
				return " " + value;
			}
			return value;
		}

		private static void AddStyleIfNotExists(IDictionary<string, object> attributes, string name, object value)
		{
			string newStyle = string.Format("{0}:{1};", name, value);
			if (!attributes.ContainsKey("style") || attributes["style"] == null)
			{
				attributes["style"] = newStyle;
			}
			else
			{
				string curStyle = attributes["style"].ToString();
				if (!curStyle.Contains("width"))
					attributes["style"] = newStyle + curStyle;
			}
		}

		private static void CopyAttributes(IDictionary<string, object> attributesFrom, IDictionary<string, string> attributesTo)
		{
			attributesFrom.ForEach(c => attributesTo[c.Key] = Convert.ToString(c.Value));
		}
	}
}